package com.fakeDYChat.common.user.service.impl;

import com.fakeDYChat.common.common.constant.RedisKey;
import com.fakeDYChat.common.common.utils.JwtUtils;
import com.fakeDYChat.common.common.utils.RedisUtils;
import com.fakeDYChat.common.user.service.LoginService;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    public static final int TOKEN_EXPIRE_TIME = 2;
    public static final TimeUnit TIME_UNIT = TimeUnit.HOURS;
    private final JwtUtils jwtUtils;

    public LoginServiceImpl(JwtUtils jwtUtils) {
        this.jwtUtils = jwtUtils;
    }

    /**
     * 刷新token有效期
     *
     * @param token
     */
    @Override
    public void renewalTokenIfNecessary(String token) {
        Long validUid = getValidUid(token);
        if (Objects.isNull(validUid)) {
            //refresh_token过期的情况
            return;
        }
        String userTokenKey = getUserTokenKey(validUid);
        Long expire = RedisUtils.getExpire(userTokenKey, TIME_UNIT);
        if (expire == -2) {
            //键值过期的情况
            return;
        }
        if (expire < (TOKEN_EXPIRE_TIME / 2)) {
            //给refresh_token续期
            RedisUtils.expire(userTokenKey, TOKEN_EXPIRE_TIME, TIME_UNIT);
        }
    }

    @Override
    public String login(Long uid) {
        //todo token生成逻辑
        String token = jwtUtils.createToken(uid);
        //存入uid进Redis
        RedisUtils.set(getUserTokenKey(uid), token, TOKEN_EXPIRE_TIME, TIME_UNIT);
        return token;
    }

    /**
     * 如果token有效，返回uid
     *
     * @param token
     * @return
     */
    @Override
    public Long getValidUid(String token) {
        Long uid = jwtUtils.getUidOrNull(token);
        if (Objects.isNull(uid)) {
            return null;
        }
        String oldToken = RedisUtils.get(getUserTokenKey(uid), String.class);
        return Objects.equals(oldToken, token) ? uid : null;
    }

    private static String getUserTokenKey(Long uid) {
        return RedisKey.getKey(RedisKey.USER_TOKEN_STRING, uid);
    }
}
